perm filename MBOX.DGL[UP,DOC]9 blob
sn#346004 filedate 1978-04-06 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00014 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 Abstract
C00004 00003 FRM box output
C00007 00004 A little bit about loading FRM Event Lists into the SIX
C00010 00005 Samson box output
C00016 00006 Bells and whistles for MBOX output.
C00029 00007 The scanner-parser file scanner.
C00033 00008 Setting timing variables for Samson box output:
C00036 00009 PRINT statement, strings, RDNUM.
C00038 00010 Even less about loading Samson box command streams
C00050 00011 Loading your own instruments.
C00056 00012 Loading MBOX
C00060 00013 GOSC GOSCVF SHAPE LINGER GEN MOD MIX RANDOM FILTER REV GENFM1 GENFM3 SPACE
C00067 00014 That's about all you need to know. If you have any questions,
C00070 ENDMK
C⊗;
Abstract
This describes the program MBOX, written by Gareth Loy,
which takes PLAY block code suitable for MUSCMP, such as the output of
SCORE or whatever and translates it into either a binary command stream
for the Samson box or an Event List for the FRM box.
The program is made to resemble MUSCMP insofar as is possible, with some
additions and changes, as the realtime instruments require.
Input can be done from a file, or from the console, as in MUSCMP;
FRM box output
A simple example should suffice for FRM box code, as at this point it's
input is quite simple, it rigidly requires that the begin time be in P1,
duration in P2, and frequency in Hz in P3. All other fields are ignored.
The following is an input file for the FRM box:
INSTRUMENT FRM soprano alto;
BOXTYP←FRMDEV;
PLAY foo;
soprano 0.00 0.14 AS;
soprano 0.15 1.00 B/2;
alto 1.00 6.67 AS*2;
FINISH;
EXIT;
Capitalized words are reserved words in MBOX.
The INSTRUMENT definition can be used to declare any number of instruments
(however the FRM box only can handle 32). At the moment, for FRM box
output only, they are non-reentrant instruments like in MUSCMP, however
this may change.
The statement boxtyp←frmdev makes MBOX put out an Event list. That
statement wouldn't be necessary if the input file had the extension .FRM,
which would also set boxtyp.
Boxtyp←samdev will switch the mode to Samson code (but don't change boxes
in the middle of the stream!).
The output will go to a file FOO.PLA as specified after the PLAY block
declaration. (The .PLA extension is added by default.) Three notes
will be played as indicated. Notice that the two Soprano notes cannot sound
simultaneously in FRM code (for now).
The EXIT command is optional, and just
forces the program to quit instead of asking for more input. Here's an
example of running the file:
.r mbox
Input file: foo.frm
Reading input file: DSK:FOO.FRM[SAM,DGL]
Command output to file: DSK:FOO.PLA[SAM,DGL]
Finishing command output file DSK:FOO.PLA[SAM,DGL]
End of SAIL execution
↑C
.
A little bit about loading FRM Event Lists into the SIX
Once you've got your Event List, do the following:
Find some program with .RTJ as an extension on [FRM,MUS] that produces a
timbre and has at least as many voices as you want. These files are FAIL
code, and the Event Lists are macros that are loaded into the code when it
is compiled. The whole thing is then loaded into the SIX, which runs the
code as a real time job, grabbing the FRM and passing it commands. If no
.RTJ program exists which suits your taste and or number of voices, you'll
have to hack around inside one of them yourself, which works only if you
know FAIL.
For example, to synthesize the example of FRM code on the previous pages,
I (with Dick's help) created an .RTJ file called FANFA.RTJ which has two
trumpets with the unlikely names of Soprano and Alto (strumpets?!?). Then
I compiled a copy of this master FAIL file into a dump that contained also
the Event List:
.al frm,mus
.Load foo←fanfa.rtj/compile/save
Somwhere along the way the FAIL compiler asked me to type in the name of
the .PLA file containing the Event List, and I typed, exactly:
file foo.pla <meta> <control> <linefeed>
The .PLA file must be on FRM,MUS, the FAIL compiler aparently can't find
other areas. When compilation and loading were done, then to hear the
score type:
.ru ten
then enter the dump file for the RTJ and follow directions (Fire when
ready Gridly!).
Samson box output
Here's an example of getting Samson box output. It's a bit more
complicated by virtue of being more controllable. There is code for
Samson instruments predeclared in MBOX. For a list of the available
instrument templates see where they are described, several pages hence.
To use them, just call them when you want them, no need to use the INSTRUMENT
statement.
They perform a variety of simple functions such as sinusoid generation,
fm, filtering, reverb, etc.
They are able to use functions created by
Andy's SEG record generating program, SYS:TFUN (If you
don't know about this, some documentation is available in INTERM.TXT[DOC,MUS],
under the subject of FUNED and EDFUN, there is also in the program itself)
or Leland's FUNC program.
Unlike MUSCMP (that is, NEWMUS and MUSIC and friends) the
instruments can be reentered. What happens is that MBOX sprouts a new
instrument of the same class if one like it was already running. To be
specific, overlapping the same instrument with itself will work (up to the
limit of the Samson box hardware = 256 oscillators, 128 modifiers).
Here's an example of an input file:
RECORD gosc;
PLAY ASK;
GOSC 0 0.14 AS test1 1 0 A_RUNNING+LPLUSQ+SINE 0 ZERO OUTA;
GOSC 0.00 1.14 B/2;
GOSC 1.00 6.67 AS*2;
FINISH;
EXIT;
Reserved words are capitalized.
The only formal addition is that of the RECORD declaration. The argument to that
command is the name of a file with an assumed extension of .FUN which
contains SEG type record functions created by Andy's TFUN program. There
were several records in the file GOSC.FUN when this example was made, among
them amp1 etc. Each described a typical amplitude function that
ranged between 0 and 1. These are
then included in the instrument calls just the way that, for instance, F1
would be passed to a MUSCMP instrument.
Another way to read in functions is to use the reserved word INSERT
followed by a filename, like: INSERT foo.fun; Here the file extension is
required, whereas with RECORD, .FUN is assumed. INSERT is more general
than RECORD and can be used to read in any kind of file be it .FUN files
or files containing INSTRUMENT definitions, PLAY blocks, etc. When MBOX
sees the INSERT statement it jumps to the named file and begins executing
from it. When that file is exausted, it returns to the file where it read
the INSERT. (Files can be nested up to 15 deep where one file inserts the
next which inserts the next, etc.)
Still another way to read in function files is when MBOX asks for input
files.
The other funny things are as follows: P5 is a scaling term for the
record, P6 is a d.c. offset term for the record, next comes the running
mode (see LRNSAM.DGL[UP,DOC] for details about generator parameters),
followed by the fm input term (here set to read from a predeclared
location that returns zeros only) and finally the sum memory location that
the whole thing writes into.
This file ran as follows:
.r mbox
MUSBOX: 17-FEB-78
Input file: gosc
Reading file: DSK:GOSC.SAM[SAM,DGL]
Reading record file: DSK:GOSC.FUN[SAM,DGL]
9 functions found:
AMP9 AMP8 AMP7 AMP6 AMP5 AMP4 AMP3 AMP1 AMP2
Output file: gosc
Command file: DSK:GOSC.DOA[SAM,DGL]
PFINISH: Scheduling statistics:
Number of waits = 8, Max Q len = 3
Average Q len = 2
Finishing command output file DSK:GOSC.DOA[SAM,DGL]
End of SAIL execution
↑C
.
**********
NOTE: It is possible to make up your own Samson instruments and load
them with MBOX. To do this is not difficult, but requires more explanation
than I care to go into here. See me. Someday it will be possible
to dynamically load instruments utilizing the Lisp Loader.
Bells and whistles for MBOX output.
Declarations, etc.:
------------------------------------------------------------------------
INSTRUMENT takes a template name as its first argument then any number
of other unique identifiers which will be associated with
this template;
COMMON same as INSTRUMENT, but someday INSTRUMENT will be redefined
to cause MBOX to look up a .REL file full of instrument code
and read it in. At that time COMMON will be the only way
to associate a template with a series of other identifiers
that you want to also point to that template;
PLAY begins a PLAY block. May be followed with an optional argument
specifying an output file, which will have the default extension
".DOA" for SAMSON box output or ".PLA" for FRM output. No
filename defaultts to "TEST" plus extension. Or, instead
of a filename you can say "ASK" and MBOX will prompt the user
at execution time and get the filename that way.
Entering a PLAY block initializes lots of things as described
below;
FINISH Ends a PLAY block, forces all instruments to quit, closes
the output file. An optional argument after the FINISH statement
specifies the number of seconds to wait after the end of the
last instrument before turning off the dacs and doing a reset;
RECORD takes a filename with default extension ".FUN" and uses
a special handler to read in SEG functions. Knows about "ASK";
INSERT takes a filename with default extension ".SAM", suspends
execution of current level, jumps to the new file and
continues execution there, returning to this level when
that is exausted. Files can be inserted up to 15 deep.
.FUN files can also be read in this way by adding the
explicit extension. Knows about "ASK";
EXIT forces MBOX to quit and returns you to the monitor, after
closing all files;
TEMPLATE assigns different names to the instrument code. Takes up to 16
arguments, writes over the default template names starting
with ins0. Usefull if you write your own instruments,
otherwise, forget it;
************************************************************************
User settable variables to set before entering PLAY block:
The following variables are tested by MBOX when it scanns a PLAY
statement to set overall conditions. To have any effect, therefore, they
must be set before issuing the PLAY statement.
------------------------------------------------------------------------
boxtyp assign either samdev or frmdev to determine the type of
output, defaults to samdev. This is also settable by
having your input file have either extensions .SAM
or .FRM respectively;
nptix assign to how many processing ticks, defaults to 96;
nutix assign to how many update ticks, defaults to 32;
ttix total of the above two, this determines the sampling rate;
srate will contain sampling rate calculated from nptix and nutix;
mag will have frequency scaling calculated from srate;
noutchans assign between 0 and 4 output channels,
defaults to quad;
whichside assign 0 for dacs to read from generator sum memory only,
positive for modifier side only, negative for both sides,
defaults to negative;
filters for low pass filters on the dacs, assign any of these values:
"unfiltered" ≡ bypass analog filters,
0 ≡ 4.5 kHz
1 ≡ 9.0 kHz
2 ≡ 13.5 kHz
3 ≡ 18.0 kHz,
defaults to 3;
packing set to left_justified, right_justified or full_word,
defaults to full_word which is interpreted by LOWER to
only load full_word when necessary;
optimization set to optimize or non_optimize to determine whether
LOWER will pack more commands per word where possible,
defaults to non_optimize (this may change);
debug assign with any summation of
debug_instruments to see what values they are passed,
debug_scanning to see what is read in from a file,
debug_arithmetic to see how MBOX does it's arithmetic,
debug_stack to see the contents of arithmetic stacks,
debug_scheduling to see how MBOX sprouts instruments;
************************************************************************
Variables preset by MBOX:
All of the following are set up when you issue a PLAY statement.
They will not be assigned actual values until then! These are writable
variables, so if you want to clobber them you can. No guarantees, however
that doing so will get you anywhere.
------------------------------------------------------------------------
zero predeclared sum memory location to always return zero;
outa, outb...d predeclared sum memory locations to stuff generator output;
outma, outmb..d predeclared sum memory locations to stuff modifier output;
************************************************************************
Reserved procedures in MBOX:
These claim and return the address of the next free sum memory
location. They require initialization induced by the PLAY statement, and their
results are invalid outside a PLAY block.
------------------------------------------------------------------------
gen_sum returns the next free last pass sum memory location;
mod_sum likewise for modifiers;
print prints the subsequent argument on the user's screen;
rdnum returns a real number from the user;
getdm takes length of delay memory desired as argument,
returns base address if successful in claiming memory,
else generates error(under development);
rand returns a random number;
************************************************************************
Preloaded variables:
These variables are set up when MBOX is entered and are valid
anywhere. They are assigned the values indicated below them.
------------------------------------------------------------------------
A,AS,B,C,CS,D,DS,E,F,FS,G,GS;
440,466.16,493.89,261.62,277.18,293.66,311.13,329.63,349.23,369.99,391.99,415.31;
************************************************************************
Symbolic constants:
These are predeclared symbols. They cannot be assigned to,
but may be assigned from (e.g. a←pi, but not pi←a).
-------------------------------------------------------------------------
Generators:
g_inactive, g_pause, a_running, b_running, g_wait, c_running,
data_read, data_write, dac_write,
lplusq, lminusq, lexpplus, lexpminus,
sum_of_cosines, sawtooth, square, pulse_train, sine, sin_fm;
Modifiers:
m_inactive, u_noise, tr_u_noise, latch, threshold, invoke_delay_unit,
notwopoles, two_0poles, two_1poles,
notwozeroes, two_0zeroes, two_1zeroes,
int_mixing, one_pole, mixing, one_zero,
four_quad_multiply, am,
maximum, minimum, signum, zero_crossing_pulser,
add_sum_memory, replace_sum_memory;
Delay units:
delay,
d_inactive,
delayline, table_lookup, round_table_lookup;
Debugging:
debug_instruments, debug_arithmetic, debug_scheduling, debug_scanning,
debug_stack,debug_records,debug_template;
Initialization:
samdev,frmdev,
unfiltered,
optimize,non_optimize,
right_justified,left_justified,full_word;
Misc. commands:
pause_clear,wait_clear;
Constants:
pi,
true,false;
************************************************************************
Misc. things:
------------------------------------------------------------------------
COMMENT can be used to enter comments in the text, everything scanned
until the first semicolon is seen will magically disappear;
< this is also a comment charactor and causes MBOX to flush the
entire input line. It does not break on a semicolon, but flushes
everything until it sees a <crlf>;
' When this charactor is scanned at the beginning of a number
the immediately subsequent value is presumed to be in octal.
↓ This charactor used inside a PRINT statement will cause a
<crlf> to be printed on the user's terminal;
ASK When supplied as an argument anywhere that a filename is expected,
MBOX will prompt the user for a filename instead (e.g. PLAY ASK;);
************************************************************************
The scanner-parser; file scanner.
MBOX has an inverse Polish expression scanner that works in
the usual fashion.
Precedence of operators is:
[")"]["¬"] unary negation
["↑"] exponentiation
["*"]["/"] ["⊗"] left shift
["+"]["-"]
["("]["←"]
Multiple operations of the same precedence are done left to right.
MBOX has one filename handler for all the different kinds
of files it reads. In all the modes that follow, it is possible to
put in any number of filenames (seperated by a comma or
space, or whatever) and they will be acted on in turn. Additionally,
if the argument ASK is given instead of a filename, then MBOX will prompt
the user for the filename string. (This is not too useful at INPUT FILE
level obviously, but quite handy elsewhere, such as in the PLAY statement.)
At INPUT FILE level, the default extension is .SAM, if that is not
found, then .FRM is tried. There is no default device here, since a
<cr> does not look up a filename but prompts for TTY input.
This level can also be used to lookup function files if the .FUN extension
is explicitly added to the filename. MBOX can be exited by typing <alt>
to the INPUT FILE prompt.
TTY input level is arrived at by typing a <cr> to INPUT FILE
level, which prompts with a ">". To return to INPUT FILE level, type
<alt>. (The next <alt> would exit MBOX.)
FILE input level is when MBOX is snarfing down a file that
you pointed it to. This level and TTY level are handled identically,
so whatever you say in a file you can also type in at a TTY and vice
versa.
INSERT can be used when in TTY or FILE input levels to request
another file to be executed. Execution of the new file(s) begins immediately.
It has the same defaults as INPUT FILE level.
RECORD input statement accepts the default .FUN extension, otherwise
it behaves exactly like the other input modes.
The PLAY statement takes an optional argument for the name
of the output .DOA file (DOA by the way stands for DataoA, now arn't you
glad you asked?) Default filename is TEST.DOA. Additionally, saying
PLAY ASK; will prompt the user for an output filename.
Setting timing variables for Samson box output:
You can now set any of srate, mag, ttix (total ticks), nptix
(number of processing ticks) or nutix (number of update ticks) and
the remainder of these variables will be set to reasonable values
(it sez here). Hence, you can say srate←25600; and the right things
get done to accomplish that. However, do not try to reset any of
these variables inside a play block, as unpredictable things (bugs)
will happen. This should be fixed in the near future (1/31/78).
Additional warnings: The "right thing" may not always be
unambiguous, and mbox does what it can. For instance, simply
setting ttix does not specify the division between nptix and nutix,
so this is defaulted to a rather arbitrary ratio between the two
(3/1). This ambiguity can be overcome by setting nptix and nutix
yourself, but letting mbox do it should be ok most of the time.
Also, since the thing that really determines the sampling rate
is the integer ttix, setting srate (which is a real) will give you
instead the srate calculated from the nearest integer value of ttix.
Everything else is set from this also. So if the srate you get is
not exactly the srate you set, that's why.
Processing ticks are restricted to be ≥2 and ≤256.
Update ticks are restricted to be ≥2.
Total ticks are always 8 more than the sum of update and processing
ticks (to account for overhead ticks).
The numbers actually compiled into the DOA command stream
will be slightly different, reflecting how the box likes to think
about these things, that is:
Highest tick will be ttix-2. This is because the counter must
start at 0, and be one less than the number required (see the spec.).
Highest proc. tick will be nptix-1 also because counter must start
at 0, again as per spec.
PRINT statement, strings, RDNUM.
There is a print statement that you can do all sorts of
bizarre things with such as:
PRINT "now replace a with b",a←b;
PRINT -(1/(2↑.5)*pi,"look ma no hands",1 ⊗ 20;
PRINT also works for getting information about functions.
PRINT amp1
will give you its type, where it is on the list, the number of elements,
etc.
The charactor "↓" is reserved in MBOX and prints out
a carriage return - linefeed on the users terminal. Strings
must be surrounded by quotes, quotes within quotes are not supported.
(A hidden benefit of the string implementation is that you can
surround anything in quotes and it will magically dissapear except
when it is inside a PRINT statement, i.e., it acts just like a COMMENT:
"now replace a with b"a←b;).
RDNUM takes a string argument from the user and returns
it to MBOX. The following asks for a number and deposits it in A;
PRINT "Type your mother's birthdate",↓;
A←RDNUM;
Even less about loading Samson box command streams
THIS IS OBSOLETE, R SAMX INSTEAD.
There are two things you can do with the output of MBOX (that I know of)
namely disassemble it to see if it looks reasonable, or play it to
see if it sounds reasonable.
Playing the commands currently requires that you make up a realtime
job to be loaded on the SIX that actually runs SAM. The best way to do this
is to not ask any questions, but to make a DO file called something
like CVSND.DO that looks like this:
ru cvos↔?a.doa↔?a.str↔loa ?a←rehead.rtj+?a.str+tail.rtj↔r ten↔?a↔
Then you need the sources of the things the DO file will call. So copy into
your area the following files:
cvos.dmp[sam,mus],
rehead.rtj[sam,dgl],
tail.rtj[sam,dgl].
Then type to the monitor:
.DO CVSND
to which it will respond:
a= _
to which you respond (in this case):
foo<cr>
It will then go away and print various things on your screen and eventually
come back to ask you to type <cr> to start job. Do so and follow instructions.
Typing <alt> will exit this program.
Disassembly is done with Mark Kahrs' program DAB (a lil' dab'l do
ya') which stands for DisAssemble the Box. You take the command file, in
this case FOO.doa, and
.r dab
input file: foo.doa
output file: foo.dab
↑C
.
et foo.dab/r
and this is what you get (egads!): (please note, these opcodes may not be correct!)
0 20000005001 GFM 0 1 ;fm address
1 15401 GO 1 1 ;sweep rate
2 10400005001 GMODE 200 1 ;mode dac l+q sum
3 1400600 HiProc 140 ;Highest Proc Tick
4 2000610 HiTick 200 ;Highest Tick
5 10000005002 GMODE 0 2 ;mode inactive l+q sum
6 20000004002 GSUM 0 2 ;sum memory
7 5402 GO 0 2 ;sweep rate
8 314022002 GJr 31402 2 ;frequency
9 20000005002 GFM 0 2 ;fm address
10 10000004002 GL 0 2 ;asymptote
11 1002 GQr 0 2 ;decay exponent
12 3002 GP 0 2 ;delta
13 4402 GK 0 2 ;angle
14 20000003402 GM 0 2 ;scale
15 10000003402 GN 0 2 ;ncosines
16 13610005002 GMODE 1704 2 ;mode a_run l+q cos
17 10000005003 GMODE 0 3 ;mode inactive l+q sum
18 20000004003 GSUM 0 3 ;sum memory
19 5403 GO 0 3 ;sweep rate
20 154052003 GJr 15405 3 ;frequency
21 20000005003 GFM 0 3 ;fm address
22 10000004003 GL 0 3 ;asymptote
23 1003 GQr 0 3 ;decay exponent
24 3003 GP 0 3 ;delta
25 4403 GK 0 3 ;angle
26 20000003403 GM 0 3 ;scale
27 10000003403 GN 0 3 ;ncosines
28 13610005003 GMODE 1704 3 ;mode a_run l+q cos
29 3002 GP 0 2 ;delta
30 1002 GQr 0 2 ;decay exponent
31 3003 GP 0 3 ;delta
32 1003 GQr 0 3 ;decay exponent
33 6070420 Dwell 607 ;Dwell (Linger)
34 3002 GP 0 2 ;delta
35 20550420 Dwell 2055 ;Dwell (Linger)
36 3002 GP 0 2 ;delta
37 60400420 Dwell 6040 ;Dwell (Linger)
38 3002 GP 0 2 ;delta
39 61640420 Dwell 6164 ;Dwell (Linger)
40 3003 GP 0 3 ;delta
41 105550420 Dwell 10555 ;Dwell (Linger)
42 3002 GP 0 2 ;delta
43 121700420 Dwell 12170 ;Dwell (Linger)
44 3002 GP 0 2 ;delta
45 1002 GQr 0 2 ;decay exponent
46 210070420 Dwell 21007 ;Dwell (Linger)
47 3003 GP 0 3 ;delta
48 613010420 Dwell 61301 ;Dwell (Linger)
49 3003 GP 0 3 ;delta
50 1067500420 Dwell 106750 ;Dwell (Linger)
51 3003 GP 0 3 ;delta
52 10000005004 GMODE 0 4 ;mode inactive l+q sum
53 20000004004 GSUM 0 4 ;sum memory
54 5404 GO 0 4 ;sweep rate
55 630042004 GJr 63004 4 ;frequency
56 20000005004 GFM 0 4 ;fm address
57 10000004004 GL 0 4 ;asymptote
58 1004 GQr 0 4 ;decay exponent
59 3004 GP 0 4 ;delta
60 4404 GK 0 4 ;angle
61 20000003404 GM 0 4 ;scale
62 10000003404 GN 0 4 ;ncosines
63 13610005004 GMODE 1704 4 ;mode a_run l+q cos
64 1110700420 Dwell 111070 ;Dwell (Linger)
65 3004 GP 0 4 ;delta
66 1004 GQr 0 4 ;decay exponent
67 1232600420 Dwell 123260 ;Dwell (Linger)
68 3003 GP 0 3 ;delta
69 1003 GQr 0 3 ;decay exponent
70 1554270420 Dwell 155427 ;Dwell (Linger)
71 3004 GP 0 4 ;delta
72 2545240420 Dwell 254524 ;Dwell (Linger)
73 3004 GP 0 4 ;delta
74 5520130420 Dwell 552013 ;Dwell (Linger)
75 3004 GP 0 4 ;delta
76 7502050420 Dwell 750205 ;Dwell (Linger)
77 3004 GP 0 4 ;delta
78 10606000420 Dwell 1060600 ;Dwell (Linger)
79 3004 GP 0 4 ;delta
80 1004 GQr 0 4 ;decay exponent
81 0 Noop ;Misc No effect
Loading your own instruments.
(This is currently under development, sorry for the inconvienience,
I hope construction will be done shortly, but meanwhile, pardon
my dirt!)
Currently there is only one way to do this, by using
the system loader to load in your instruments with the MBOX scanner.
MBOX figures out from the INSTRUMENT statement what template
to associate with what set of instrument names. The template
name in the INSTRUMENT definition is matched up against a list of
preloaded template names, and the right instrument template procedure
(the one that does the actual stuffing of commands) is called
by using the number of the array element where this template name
is found in the template table. It takes this number and uses
it in a case statement to figure out which procedure to call.
The actual calling of the procedure is done in InsCal.
The names of the procedures in the InsCal case statement are named
Ins0 through Ins17.
If you don't want to use the predeclared instrument template
names (likely, if you are rolling your own) then you can overwrite
the default names using the TEMPLATE declaration. The set of
names following the declaration will then become the only template
names available and they will be matched up starting from
Ins0.
Your instrument template should look like this:
(color this in SAIL)
∂17-Feb-78 0316 JOS MBOX
What is necessary to increase the number of allowed instruments in MBOX?
I only have 2 slots left ( assuming ins14 is the last, 3 if ins15 is last ).
I need room to play around with the filters in my own version of MBOX.
Also, I notice that when an instrument is named twice in score ( overlapping ),
only the most recent invocation makes it through. Is this the way things are
supposed to be ?
In general, however, MBOX is doing everything right...HOORAY!
[DGL - ins15 is the last in the current version.
To increase the number of instruments would involve the following
three steps:
1) In SAMINS.SAI, change the upper boundary of the template
identifier table, "tplLen" to the desired size. Add string preload
identifiers to correspond to the procedures to be added. Change the
pointer to the end of the preloaded table, "preLdTemplateLen" to equal the
highest number of instrument you will use (typically it will equal the
length of the array). The pointer to the end of the preloaded table,
"tplPtr" is initialized from preLdTemplateLen, and the array is scanned
from end to beginning. Here is the relevant code from
SAMINS.SAI[SAM,DGL]. Presumably you would be making these changes to a
copy of your own. The subtract 1 in the following example is because
tplIds goes from 0.
define tplLen="17-1";
define preLdTemplateLen="17-1";
preload_with "GOSC","GOSCVF","SHAPE","LINGER","GEN","MOD","MIX","RANDOM",
"FILTER","REV","GENFM1","GENFM3","NGEN","SPACE",NULL,NULL,
"FRMINS"
;
string array tplIds[0:tplLen];
2) Add the procedures to your file of instruments, declaring
them INTERNAL. Add them also on page 2 of MBOX declaring them EXTERNAL.
3) Add the procedures to the CASE statement in InsCal
on page 7 of MBOX.
The slot corresponding to ins16 is a dummy corresponding to FrmIns.
It is a dummy because FrmIns is called seperately from the instruments
in SAMINS. It is called only when the variable boxTyp equals the
macro frmDev. So you can clobber "FRMINS" on the preload table with
impunity and as long as boxTyp≠frmDev (the usual case) SAMINS ins16 will
be called (presuming that you've taken the trouble to put one out there).
What could be simpler!?!...
-Gareth]
Loading MBOX
I try to keep the most recent export version of MBOX.SAI on
[SAM,MUS], but if that one doesn't work, try MBOX.OLD[SAM,DGL].
The version under development is usually MBOX.SAI[SAM,DGL].
The old dump from the system is kept in MBOX.OLD[SAM,MUS].
To get a copy of MBOX for your very own, copy onto your
area the following files from [SAM,MUS]:
MBOX.SAI,
MBOX.HDR,
SAMTBL.SAI
SAMINS.SAI,
PRSNAM.REL,
FRMINS.REL, if you intend to do FRM output,
If you have made changes to SAMINS or MBOX or anything else, the
way to recompile is any or all of the following:
1) Changed only MBOX.SAI and/or MBOX.HDR and/or SAMTBL.SAI:
.load MBOX/sav
2) Changed only SAMINS.SAI, didn't touch any files in (1):
.com SAMINS
.loa MBOX/rel/sav
3) Changed any of INTERM.SAI, LOWER.FAI [SAM,MUS]
.loa MBOX/rel/sav
Since these are the most popular things to diddle with, I'll leave
the explication to that.
How it all hangs together:
MBOX.SAI requires the following files:
require "MBOX.HDR" source_file;
require "SAMTBL.SAI" source_file;
require "SAMINS.REL" load_module;
require "PRSNAM.REL" load_module;
∂ require "FRMINS.REL" load_module;
The "∂" comment charactor must be removed from in front of every
mention of FRMINS in MBOX.SAI to enable MBOX to do FRM output.
You must then recompile MBOX.SAI.
MBOX.HDR in addition calls the following files:
require "INTERM.HDR[SAM,MUS]" source_file;
require "SEGSYN.REL[MA,JAM]" load_module;
require "SYS:RECORD.DEF" source_file;
INTERM.HDR in turn calls:
require "INTERM.REL[SAM,MUS]" load_module;
require "SYS:PROCES.DEF" source_file;
require "LOWER.DEF[SAM,MUS]" source_file;
require "LOWER.REL[SAM,MUS]" load_module;
So altogether there are 12 files called by MBOX itself! Quite
a list... There is a hierarchical division of MBOX into
three levels. The "lower" level code assembles the command stream
to the Samson box. It also has a processing element allocation
scheme and contains tables and flags relating to the actual machine
architecture of the box. The "intermediate" level code groups the
routines of the lower level into bitesize chunks that do complete
functions, such as reverberation, complex fm instruments, etc.
The third level is MBOX itself which is the scanner/parser that
is used to drive the lower levels.
GOSC GOSCVF SHAPE LINGER GEN MOD MIX RANDOM FILTER REV GENFM1 GENFM3 SPACE
These are the formal calls to the instruments that are preloaded in MBOX.
∂ GOSC - fixed frequency, seg record variable amplitude;
∂ sample call:
<instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff, Mod, Ncs, Fmsum, outsum;
∂ GOSCVF - seg record variable frequency and amplitude;
∂ Sample call in an MBOX play list:
<instrument>, beg, dur, frqRec, Frscl, Froff, ampRec, Ampscl, Ampoff,
Mod, Ncs, Fmsum, Outsum;
∂ SHAPE - apply an envelope to a signal of amp up to 8.0;
∂ Sample call:
<instrument> beg,dur,ampRec,scale,offset,outadr,inadr,factor;
∂ LINGER;
∂ sample call:
<instrument> beg dur;
∂ GEN - raw call to a generator;
∂ sample call:
<instrument> Beg, Dur, Freq, Sweep, Angle, nCos, Scale,
Asym, Rate, Exp, Mod, Fmsum, Outsum, GenNum;
∂ Please note: this instrument simply passes whatever you put in the P
fields to LOWER, it does no scaling by MAG or anything whatsoever.
The only thing that is not just passed blindly to LOWER is the field
GenNum, which, if GenNum>0, will claim the so-numbered generator,
else it will take first available one that LOWER gives it.
;
∂ MOD - raw call to a modifier, no scaling of any terms;
∂ sample call:
<instrument> beg dur cf0 cf1 trm0 trm1 ain bin outloc ascl bscl mode modnum;
∂ If modNum>0 then claim that modifier, else take the first that's available;
∂ MIX - Multiply two signals by a constant factors between 0 and 8.
∂ sample call:
<instrument> beg dur factor1 factor2 in1loc in2loc outloc;
∂ RANDOM - Make random numbers scaled by a factor;
∂ sample call:
<instrument> beg dur factor trigger seed outloc;
∂ FILTER - Does one or two pole or zero fixed character filtering.
∂ sample call:
<instrument> beg dur frq R second_order all_pole inloc outloc;
∂ REV - Reverberator. Can be all-pass or comb.
To make an allpass, set g1←-g0←G;
∂ sample call:
<instrument> beg dur length g0 g1 inloc outloc;
∂ GENFM1;
∂ sample call:
<instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff,
Mode, Ncs, cfmfRatio, indexRec, index, indexOff, outsum;
∂ GENFM3;
∂ sample call:
<instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff, Mode, Ncs,
cfmfRatio1, indexRec1, index1, indexOff1,
cfmfRatio2, indexRec2, index2, indexOff2,
cfmfRatio3, indexRec3, index3, indexOff3,
outsum;
∂ NGEN;
∂ sample call:
<instrument>,beg,dur,mode,outSum,nFuncs,
frNameN,frSclN,frOffN, ampNameN,ampSclN,ampOffN;
∂ where: frNameN is a record function string name which can look like
either of these: foo1 or foo4a1, etc., i.e., it must
begin with a letter and end with a digit. This will be taken,
and the first of the series looked up and the number of them
specified in p5 will be used in the synthesis;
∂ SPACE;
∂ <instrument> beg dur nChans qRecN inLoc revOut %Rev
outLoc1 outLoc2 outLoc3 outLoc4;
∂ nChans can have a range of 0 to 4, 4 being the usual case;
∂ Output locations must be on modifier side sum memory, usually outMa→d;
∂ revOut is a sum memory location (on modifier side) that will have the
signal scaled by grev which is to be fed to the reverberators that supply
the global reverb to outMa→d;
∂ %Rev is the fraction of the direct signal to be sent to the reverberators;
∂ qRecN is a record function name described as
<group_name>&|"grev"|"lrev"|"amp"|"dop"|"chan1"|"chan2"|"chan3"|"chan4",
where the group_name is typically the same as the file which contains the
whole set, but can be anything, and the vertical bar seperates the various
functions that make up a set of quad functions. For example, if the group
name for a set of functions is "Circle", then the global reverb function
of that group is "CircleGrev". (Note: if the function name is
"circle_grev", the group name will be interpreted as being "circle_".)
All you need to specify in the play list is any one of the set of names
and it will find all the rest of the functions it wants by parsing out
the group_name, then searching for the individual functions using this
name;
∂ This instrument has no provision for local reverb (lrev);
That's about all you need to know. If you have any questions,
I just stepped out...